#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#include <stdlib.h>
#include "game_ui.h"
#include "game_play.h"
void signal_handler(int signum)
{
      move_down(dynamic_type,dynamic_change_type,dynamic_color);
      //判断游戏是否结束了   有列顶满就结束-->有行是空的，再取反
      if (check_game_over()==1)
      {
            // 恢复回显   一直没有输入，一直等着获取字符，也就没有显示回显
            recover_attr();
            //输出游戏结束了
            game_over();
            //进程退出
            exit(0);
      }
}

void game_over(){
        printf("\33[32;9H********** Game Over ********\33[0m");
        printf("\33[?25h");
        printf("\n\n");
    }
void alarm_us(int init_interval)
{
     struct itimerval value ;//=  {{1,0},{1,0}};
     value.it_value.tv_usec = init_interval;
     value.it_value.tv_sec =0;
     value.it_interval.tv_usec=init_interval;
     value.it_interval.tv_sec=0;
     setitimer(ITIMER_REAL,&value,NULL);
}


void key_contrl(){
    int  ch;
    while (1) //死循环  游戏一直进行
    {
       ch = getch();
       //如果按了q或者Q，退出游戏
       if (ch=='q'||ch=='Q')
       {
            break;
       }else if (ch=='\r')
       {
            //表示按了回车
           full_down(dynamic_type,dynamic_change_type,dynamic_color);
       } else if (ch == '\33')
       {
            ch = getch(); //[
            if (ch=='[')
            {
                ch = getch(); //A B C D
                switch (ch)
                {
                    case 'A':
                        change(dynamic_type,dynamic_color);
                        break;
                      case 'B':
                        //printf("print down!\n");
                        move_down(dynamic_type,dynamic_change_type,dynamic_color);
                        break;
                     case 'C':
                        //printf("print right!\n");
                        move_right(dynamic_type,dynamic_change_type,dynamic_color);
                        break;
                     case 'D':
                        //printf("print left!\n");
                        move_left(dynamic_type,dynamic_change_type,dynamic_color);
                        break;
                    default:
                        break;
                }
                
            }
            
       }   
    }
    
      //输出游戏结束了
        game_over();
}

struct termios term_old;
int  getch(){
    //定义两个终端
    struct termios term;

    //获取用户的输入带回显
    tcgetattr(0,&term_old);

    //关闭新终端回显
    cfmakeraw(&term);

    //把获取到写入新终端
    tcsetattr(0,0,&term);

   //获取不带回显的字符
    int result = getchar(); //a卡在这人

    //重置老终端回去
   // tcsetattr(0,0,&term_old); 
    recover_attr();

    return result;

}

void recover_attr(){
       //重置老终端回去
    tcsetattr(0,0,&term_old); 
}


void move_left(int type,int change_type,int color){

    //边界问题
    if (dynamic_x<=12)
    {
       return;
    }

    //左边碰撞
    if(check_shape(type,change_type,dynamic_x-2,dynamic_y)) 
            return;
    clear_mode_shape(type,change_type,dynamic_x,dynamic_y);
    //下轴占两个字符
    dynamic_x-=2;
    print_mode_shape(type,change_type,dynamic_x,dynamic_y,color);
}

void move_right(int type,int change_type,int color){
    int dynami_right_x = dynamic_x+2*(4-shape[type][change_type][16])-1;

    //边界
    if (dynami_right_x>=39)
    {
        return;
    }
    
     //右边碰撞
    if(check_shape(type,change_type,dynamic_x+2,dynamic_y)) 
            return;
    clear_mode_shape(type,change_type,dynamic_x,dynamic_y);
    //下轴占两个字符
    dynamic_x+=2;
    print_mode_shape(type,change_type,dynamic_x,dynamic_y,color);
}


void change(int type,int color){
  //变换类型  0-1 1-2 2-3 3-0 
    int change_type = (dynamic_change_type+1)%4;
    //获取变换的图形来判断
    //三种越界   右下
    if(dynamic_x+2*(4-shape[dynamic_type][change_type][16])-1 >= 39)
        return;
 
    if(dynamic_y+(4-shape[dynamic_type][change_type][17])-1 >= 29)
         return ;
    if(check_shape(type,change_type,dynamic_x,dynamic_y)==1)
        return;

    clear_mode_shape(type,dynamic_change_type,dynamic_x,dynamic_y);
    dynamic_change_type = change_type;
    print_mode_shape(type,dynamic_change_type,dynamic_x,dynamic_y,color);
}


void full_down(int dynamic_type,int dynamic_change_type,int dynamic_color ){
    while (1)
    {
        int  result = move_down(dynamic_type,dynamic_change_type,dynamic_color);
        if (result) //一直调用往下，触底就返回
            return;
    }
    
}


int move_down(int type,int change_type,int color){ 

    //1 触底，一路畅通直到底，被其他的方块拦住
    int dynamic_down_y= dynamic_y + 1*(4-shape[type][change_type][17])-1;
    //判断下一个是否被占用了
    if (dynamic_down_y>=29 || check_shape(type,change_type,dynamic_x,dynamic_y+1))
    {
         //1 把不能动的图报错到二维数组中
         store_current_shape(dynamic_type,dynamic_change_type,color);
         //2 初始化一个新图（type_changeType为下一个图的图像）
         init_new_shape();
         // 3 消除行
         clear_full_lines();
         //4 产生一个新的下一个
         print_next_shape();
        return 1;
    }
    clear_mode_shape(type,change_type,dynamic_x,dynamic_y);
    dynamic_y = dynamic_y+1;
    print_mode_shape(type,change_type,dynamic_x,dynamic_y,color);

    return 0;
}

int check_game_over(){
    //只要有空行就能玩
    for (int i = 0; i < 24; i++)
    {

            if(check_line_blank(i)){
                return 0;
            }
    }
    return 1;
}

/**
 * 判断空行
*/
int check_line_blank(int line){
    for (int i = 0; i < 28; i++)
    {
        //所有的都判断完了，为null才为null
        if(matrix[line][i]!=0){
            return 0;
        }
    }
    return 1;
}

void store_current_shape(int type,int change_type,int color){

   //获取y坐标作为数组行，但是要减6
    int m_line = dynamic_y - 6;
    int m_column = dynamic_x -12;
    for (int i = 0; i < 16; i++)
    {
        //执行完四个，行号+1
        if (i!=0 && i%4==0)
        {
            m_line+=1;
            m_column = dynamic_x -12;
        }
    
       if (shape[type][change_type][i] == 1)
       {
            matrix[m_line][m_column] = color; //其实这个位置，可以放1也可以
            matrix[m_line][m_column+1] = color;
       }
       m_column+=2;
    }
}

void clear_full_lines(){

    //遍历所有的行，分别判断是否已经满了，满了才消除
    int i,j,k,m;
    int flag = 0;
    for (i = 0; i < 24; i++)
    {

        //需要得到一个结果，看这行是否满了
        flag =1; //认为这行已经满了
        for (j = 0; j < 28; j++)
        {
             // 只要有一个没有满就没满，跳出循环
             if (matrix[i][j]==0)
             {
                 flag =0;
                 break;
             }
             
        }

      if (flag)
      {
            //清除数组类里面的哪行，并且上面的行整体下移
            for (k = i; k >= 0; k--)
            {
         
               if (k!=0)
               {
                    //非0行赋值它的上以行的值。
                   for (m = 0; m< 28; m++)
                    {
                        //就是把列分别赋值就ok
                         matrix[k][m]=  matrix[k-1][m];
                    }
               }else{
                    // 0行其实把里面的列赋值为0
                    for (m = 0; m< 28; m++)
                    {
                         matrix[k][m]=0;
                    }
               }  
            }
            
            //加分+动态计算等级
            score+=10;
            if (score!=0&& score%100==0)
            {
                level+=1;
                interval_value/=2;
                //重新设置下落速度
                alarm_us(interval_value);
            }
            
            //重新输出图形
            print_matrix();

            //并且打出来
            print_score_level();

      }  
    }
    
}
// y 已经加了1了,准备移动，判断里面是否有被占了。
int check_shape(int type,int change_type,int x,int y){
    //获取y坐标作为数组行，但是要减6
    int m_line = y - 6;
    int m_column = x -12;
    for (int i = 0; i < 16; i++)
    {
        //执行完四个，行号+1
        if (i!=0 && i%4==0)
        {
            m_line+=1;
            m_column = x -12;
        }
    
       if (shape[type][change_type][i] == 1)
       {
            if (matrix[m_line][m_column] !=0)
            {
                return 1;
            }
       }
       m_column+=2;
    }
    return 0;
}




